package code.framework.android.view;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.Activity;
import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;

public abstract class ListAdapterBase<T> implements ListAdapter {

	protected ArrayList<T> ts;

	protected LayoutInflater inflater;

	protected Activity activity;

	protected Context context;

	public DataSetObservable dataSetObservable;

	protected final Logger logger = LoggerFactory.getLogger(getClass());

	public ListAdapterBase(Context c) {
		context = c;
		if (Activity.class.isAssignableFrom(c.getClass())) {
			this.activity = (Activity) c;
		}
		inflater = LayoutInflater.from(c);
		dataSetObservable = new DataSetObservable();
		ts = new ArrayList<T>();
	}

	public synchronized void add(T t) {
		ts.add(t);
		dataSetObservable.notifyChanged();
	}

	public Collection<T> get() {
		return ts;
	}

	public synchronized void set(Collection<T> ts) {
		this.ts.clear();
		this.ts.addAll(ts);
		dataSetObservable.notifyChanged();
	}

	public synchronized void clear() {
		this.ts.clear();
		dataSetObservable.notifyChanged();
	}

	public Object getItem(int position) {
		return ts.get(position);
	}

	public void registerDataSetObserver(DataSetObserver observer) {
		dataSetObservable.registerObserver(observer);
	}

	public void unregisterDataSetObserver(DataSetObserver observer) {
		dataSetObservable.unregisterObserver(observer);
	}

	/**
	 * @Depreciated runtime environment does not support reflection
	 */
	public long getItemId(int position) {
		try {
			Class<?> clazz = (Class<?>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];
			logger.trace("clazz = {}", clazz);
			Method method = clazz.getMethod("getId", null);
			logger.trace("method = {}", method);
			T t = (T) getItem(position);
			logger.trace("t = {}", t);
			Object object = ts.get(position);
			logger.trace("object = {}", object);
			Object value = method.invoke(object, null);
			logger.trace("value = {}", value);
			return (Long) value;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public boolean areAllItemsEnabled() {
		return true;
	}

	public boolean isEnabled(int position) {
		return true;
	}

	public synchronized int getCount() {
		return ts.size();
	}

	public int getItemViewType(int position) {
		return 0;
	}

	public int getViewTypeCount() {
		return 1;
	}

	public boolean hasStableIds() {
		return true;
	}

	public boolean isEmpty() {
		return (getCount() == 0);
	}

	// public abstract long getItemId(int position);

	public abstract View getView(int position, View convertView,
			ViewGroup parent);

}
